p2p --enable
authorJoey Hess <joeyh@joeyh.name>
Wed, 30 Jul 2025 18:08:26 +0000 (14:08 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 30 Jul 2025 18:08:59 +0000 (14:08 -0400)
p2p: Added --enable option, which can be used to enable P2P networks
provided by external commands git-annex-p2p-<netname>

Made git-annex p2p --enable tor behave the same as git-annex enable-tor,
to make tor a bit less of a special case. However, it canot be run as root,
since it cannot take the user id parameter.

Annex/ExternalAddonProcess.hs
Backend/External.hs
CHANGELOG
Command/EnableTor.hs
Command/P2P.hs
P2P/Generic.hs
Remote/External.hs
doc/git-annex-p2p.mdwn

index 887f9f646686de02b640c87bfbc9862434746268..6e2af92d617c05ce33be24f453a080f5327f4ea6 100644 (file)
@@ -33,8 +33,9 @@ data ExternalAddonStartError
        = ProgramNotInstalled String
        | ProgramFailure String
 
-startExternalAddonProcess :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess)
-startExternalAddonProcess basecmd ps pid = do
+-- | Starts an external addon process that speaks a protocol over stdio.
+startExternalAddonProcessProtocol :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess)
+startExternalAddonProcessProtocol basecmd ps pid = do
        errrelayer <- mkStderrRelayer
        g <- Annex.gitRepo
        cmdpath <- liftIO $ searchPath basecmd
index 23977d1ce7d24c862bc27a26b8640af378089e1e..77373cf3ae8d204738e17367cabc4090e05ee6af 100644 (file)
@@ -215,7 +215,7 @@ poolVar = unsafePerformIO $ newMVar M.empty
 -- using it.
 newExternalState :: ExternalBackendName -> HasExt -> ExternalAddonPID -> Annex ExternalState
 newExternalState ebname hasext pid = do
-       st <- startExternalAddonProcess basecmd [] pid
+       st <- startExternalAddonProcessProtocol basecmd [] pid
        st' <- case st of
                Left (ProgramNotInstalled msg) -> warnonce msg >> return st
                Left (ProgramFailure msg) -> warnonce msg >> return st
index 3acf44fd330264175b38b89a60be372363cd2bff..cb1223ee0d271715ba7e06e720f4d67ebe175200 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+git-annex (10.20250722) UNRELEASED; urgency=medium
+
+  * p2p: Added --enable option, which can be used to enable P2P networks
+    provided by external commands git-annex-p2p-<netname>
+
+ -- Joey Hess <id@joeyh.name>  Wed, 30 Jul 2025 13:45:42 -0400
+
 git-annex (10.20250721) upstream; urgency=medium
 
   * Improved workaround for git 2.50 bug, avoding an occasional test suite
index c4b323d825d374a3e78cf963df534754d52a2884..f8c1d75a8d5fadf5ad4bd4288a4c56969454fd68 100644 (file)
@@ -38,11 +38,11 @@ cmd = noCommit $ dontCheck repoExists $
                "uid" (withParams seek)
 
 seek :: CmdParams -> CommandSeek
-seek = withWords (commandAction . start)
+seek = withWords (commandAction . start . Just)
 
 -- This runs as root, so avoid making any commits or initializing
 -- git-annex, or doing other things that create root-owned files.
-start :: [String] -> CommandStart
+start :: Maybe [String] -> CommandStart
 #ifndef mingw32_HOST_OS
 start os = do
 #else
@@ -53,9 +53,11 @@ start _os = do
        let si = SeekInput []
        curruserid <- liftIO getEffectiveUserID
        if curruserid == 0
-               then case readish =<< headMaybe os of
-                       Nothing -> giveup "Need user-id parameter."
-                       Just userid -> go userid
+               then case os of
+                       Just os' -> case readish =<< headMaybe os' of
+                               Nothing -> giveup "Need user-id parameter."
+                               Just userid -> go userid
+                       Nothing -> giveup "Cannot run this command as root."
                else starting "enable-tor" ai si $ do
                        gitannex <- fromOsPath <$> liftIO programPath
                        let ps = [Param (cmdname cmd), Param (show curruserid)]
index 0ee588f42ab4d69c94790eb87c18ce0f86d29db8..491355507cea7db7f3d5f7fbda55d8a6fabb174a 100644 (file)
@@ -1,6 +1,6 @@
 {- git-annex command
  -
- - Copyright 2016 Joey Hess <id@joeyh.name>
+ - Copyright 2016-2025 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -13,6 +13,7 @@ import Command
 import P2P.Address
 import P2P.Auth
 import P2P.IO
+import P2P.Generic
 import qualified P2P.Protocol as P2P
 import Git.Types
 import qualified Git.Remote
@@ -27,6 +28,7 @@ import Utility.ThreadScheduler
 import Utility.SafeOutput
 import qualified Utility.FileIO as F
 import qualified Utility.MagicWormhole as Wormhole
+import qualified Command.EnableTor as EnableTor
 
 import Control.Concurrent.Async
 import qualified Data.Text as T
@@ -40,10 +42,11 @@ data P2POpts
        = GenAddresses
        | LinkRemote
        | Pair
+       | Enable P2PNetName
 
 optParser :: CmdParamsDesc -> Parser (P2POpts, Maybe RemoteName)
 optParser _ = (,)
-       <$> (pair <|> linkremote <|> genaddresses)
+       <$> (pair <|> linkremote <|> genaddresses <|> enable)
        <*> optional name
   where
        genaddresses = flag' GenAddresses
@@ -58,6 +61,10 @@ optParser _ = (,)
                ( long "pair"
                <> help "pair with another repository"
                )
+       enable = Enable . P2PNetName <$> strOption
+                ( long "enable" <> metavar paramName
+                <> help "enable using a P2P network"
+                )
        name = Git.Remote.makeLegalName <$> strOption
                ( long "name"
                <> metavar paramName
@@ -75,6 +82,8 @@ seek (Pair, Just name) = commandAction $
 seek (Pair, Nothing) = commandAction $ do
        name <- unusedPeerRemoteName
        startPairing name =<< loadP2PAddresses
+seek (Enable netname, _) = commandAction $
+       enableNetwork netname
 
 unusedPeerRemoteName :: Annex RemoteName
 unusedPeerRemoteName = go (1 :: Integer) =<< usednames
@@ -316,3 +325,16 @@ setupLink remotename (P2PAddressAuth addr authtoken) = do
                return LinkSuccess
        go (Right Nothing) = return $ AuthenticationError "Unable to authenticate with peer. Please check the address and try again."
        go (Left e) = return $ AuthenticationError $ "Unable to authenticate with peer: " ++ describeProtoFailure e
+
+enableNetwork :: P2PNetName -> CommandStart
+enableNetwork netname@(P2PNetName name)
+       | name == "tor" = EnableTor.start Nothing
+       | otherwise = starting "p2p enable" ai si $ next $ do
+               addrs <- liftIO $ getAddressGenericP2P netname
+               when (null addrs) $
+                       giveup $ genericP2PCommand netname ++ " did not output any P2P addresses" 
+               mapM_ storeP2PAddress addrs
+               return True
+  where
+       ai = ActionItemOther (Just (UnquotedString name))
+       si = SeekInput []
index 9dc118f820e505bbfd27b67214b991f436503fc9..ac80f3eedfe8a3df25cc285edae340e39fc59a70 100644 (file)
@@ -25,18 +25,18 @@ connectGenericP2P netname (UnderlyingP2PAddress address) =
 socketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> CreateProcess
 socketGenericP2P netname (UnderlyingP2PAddress address) =
        (proc (genericP2PCommand netname) ["socket", address])
-               { std_in = CreatePipe
+               { std_out = CreatePipe
                }
 
 addressGenericP2P :: P2PNetName -> CreateProcess
 addressGenericP2P netname =
        (proc (genericP2PCommand netname) ["address"])
-               { std_in = CreatePipe
+               { std_out = CreatePipe
                }
 
 getSocketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> IO (Maybe (OsPath, ProcessHandle))
 getSocketGenericP2P netname address = do
-       (Just hin, Nothing, Nothing, pid) <- createProcess $
+       (Nothing, Just hin, Nothing, pid) <- createProcess $
                socketGenericP2P netname address
        hGetLineUntilExitOrEOF pid hin >>= \case
                Just l | not (null l) -> return $ Just (toOsPath l, pid)
@@ -44,7 +44,7 @@ getSocketGenericP2P netname address = do
 
 getAddressGenericP2P :: P2PNetName -> IO [P2PAddress]
 getAddressGenericP2P netname = do
-       (Just hin, Nothing, Nothing, pid) <- createProcess $
+       (Nothing, Just hin, Nothing, pid) <- createProcess $
                addressGenericP2P netname
        go [] hin pid
   where
index 2b26e322397f7c366950f5f091fd8b2c400a3d3f..dcfbaacbf2372e2453ffa825faeeb8858c7a670c 100644 (file)
@@ -673,7 +673,7 @@ startExternal' external = do
                n <- succ <$> readTVar (externalLastPid external)
                writeTVar (externalLastPid external) n
                return n
-       AddonProcess.startExternalAddonProcess externalcmd externalparams pid >>= \case
+       AddonProcess.startExternalAddonProcessProtocol externalcmd externalparams pid >>= \case
                Left (AddonProcess.ProgramFailure err) -> do
                        unusable err
                Left (AddonProcess.ProgramNotInstalled err) ->
index 7d4c6ee80a68b0ac438458075a286c6a64faf347..deb79c89aac0a9b3b0d9868d51c182ba074b3664 100644 (file)
@@ -25,7 +25,9 @@ for documentation about how to create such a program.
 * `--enable <netname>`
 
   Enable using the P2P network with the specified name.
-  This needs the helper program `git-annex-p2p-<netname>` to be installed.
+
+  For networks other than tor, this needs the helper program
+  `git-annex-p2p-<netname>` to be installed.
 
   After this command is run, `git annex remotedaemon` can be run to serve
   incoming connections from peers, and `git-annex p2p --pair` or